---
title: Quick Start
description: The fastest and simplest way to start using Takumi.
icon: Axe
---

Takumi is an **image rendering engine** written in Rust. The design is mainly inspired by [satori](https://github.com/vercel/satori), but with a focus on portability and performance (2-10x compared to next/og in [Image Bench](https://image-bench.kane.tw/)).

You can try Takumi in [Playground](/playground) without any installation.

## Installation

The fastest/simplest way to use Takumi is with the `ImageResponse` API. It handles the internal state for font & image cache and it tries to be compatible with [Next.js ImageResponse API](https://nextjs.org/docs/app/api-reference/functions/image-response).

```npm
npm i @takumi-rs/image-response
```

### Additional Bundler Setup

Takumi offers two types of bindings for different environments. [`@takumi-rs/core`](https://www.npmjs.com/package/@takumi-rs/core) for Node.js and [`@takumi-rs/wasm`](https://www.npmjs.com/package/@takumi-rs/wasm) for WebAssembly.

#### Node.js Runtime

<Accordions type="single">
  <Accordion title="Next.js">

By default Next.js bundles the `@takumi-rs/core` package, which requires native Node.js `require` function to resolve the native binary. You need to opt-out from the bundling by setting the `serverExternalPackages` option.

```ts title="next.config.ts"
export const config = {
  serverExternalPackages: ["@takumi-rs/image-response"],
};
```
  </Accordion>
  <Accordion title="Vite (SSR)">
Opt-out from the bundling by setting the `ssr.external` and `optimizeDeps.exclude` options.

```ts title="vite.config.ts"
export default defineConfig({
  ssr: {
    external: ["@takumi-rs/image-response"],
  },
});
```

If you still encounter issues after all, try opening issues on GitHub or try the WebAssembly version instead.

  </Accordion>
  <Accordion title="Nitro (Tanstack Start)">
First, install the `@takumi-rs/core` package where we grab the optional dependencies from.

```npm
npm i @takumi-rs/core
```

Then, configure Nitro to externalize the dependencies and include the optional dependencies in the trace.

```ts title="vite.config.ts"
import takumiPackageJson from "@takumi-rs/core/package.json" with {
  type: "json",
};

export default defineConfig({
  nitro: {
    externals: {
      external: ["@takumi-rs/core"], // [!code highlight]
      traceInclude: Object.keys(takumiPackageJson.optionalDependencies), // [!code highlight]
    }
  }
});
```
  </Accordion>
</Accordions>

#### Edge Runtime / Browser

<Accordions type="single">
  <Accordion title="Cloudflare Workers">
Cloudflare Workers prohibited fetching WASM then initialize on the fly. You can import from `@takumi-rs/wasm/takumi_wasm_bg.wasm` and pass it to the `module` option.

```tsx twoslash
/** @jsxImportSource react */
// ---cut-before---

import { ImageResponse } from "@takumi-rs/image-response/wasm";
import module from "@takumi-rs/wasm/takumi_wasm_bg.wasm"; // [!code highlight]

export default {
  fetch() {
    return new ImageResponse(<div />, {
      module, // [!code highlight]
      // ...
    });
  },
}
```

And make sure you have `wrangler.jsonc` / `wrangler.toml` setup to load assets. `compatibility_date` should be set to at least `2025-10-30`.

```jsonc title="wrangler.jsonc"
{
  "$schema": "node_modules/wrangler/config-schema.json",
  "compatibility_date": "2025-10-30",  // [!code highlight]
  "rules": [
    {
      "type": "Data",
      "globs": ["**/*.ttf", "**/*.woff2"],
    }
  ]
}
```

Check the [example project](https://github.com/kane50613/takumi/tree/master/example/cloudflare-workers) with wrangler usage.
  </Accordion>
  <Accordion title="Vite">
Load the WASM file as an asset.

```tsx
import { ImageResponse } from "@takumi-rs/image-response/wasm";
import module from "@takumi-rs/wasm/takumi_wasm_bg.wasm?url";

new ImageResponse(<div />, {
  module,
})
```
  </Accordion>
  <Accordion title="Next.js with Turbopack">
This works in both Node.js and Edge runtime.

```tsx twoslash
/** @jsxImportSource react */
// ---cut-before---

import { ImageResponse } from "@takumi-rs/image-response/wasm";
import module from "@takumi-rs/wasm/next";

new ImageResponse(<div />, {
  module,
})
```
  </Accordion>
  <Accordion title="Webpack">
First, configure Webpack to recognize the WASM file as an asset.

```ts title="webpack.config.js"
module.exports = {
  module: {
    rules: [
      {
        test: /\.wasm$/,
        type: 'asset/resource',
        generator: {
          filename: 'wasm/[name].[hash][ext]'
        }
      }
    ]
  }
};
```

Then, in your code, import the WASM file and initialize the module:

```ts
import { ImageResponse } from '@takumi-rs/image-response/wasm';
import wasmUrl from '@takumi-rs/wasm/takumi_wasm_bg.wasm';

new ImageResponse(<div />, {
  module: wasmUrl,
})
```
  </Accordion>
</Accordions>

## Usage

Since `ImageResponse` extends standard [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) class, you can plug it into anywhere you want.

It comes with pre-bundled full axis (which means 100-900 weights available) [Geist](https://vercel.com/font) and Geist Mono as default fonts. [Tailwind CSS](https://tailwindcss.com/) is also supported out of the box.

<Tabs items={["Node.js", "WASM"]}>
<Tab>
```tsx twoslash
/** @jsxImportSource react */
// ---cut-before---

import { ImageResponse } from "@takumi-rs/image-response";
import { serve } from "bun";

serve({
  fetch() {
    return new ImageResponse(<Hello />, {
      width: 1200,
      height: 630,
      format: "webp",
    });
  },
});

function Hello() {
  return (
    <div tw="bg-white w-full h-full flex items-center justify-center">
      <h1 tw="text-4xl font-bold">Hello</h1>
    </div>
  );
}
```
</Tab>
<Tab>
```tsx twoslash
/** @jsxImportSource react */
// ---cut-before---

import { ImageResponse } from "@takumi-rs/image-response/wasm";
import { serve } from "bun";

  // Check the additional bundler setup section for more details.
import module from "@takumi-rs/wasm/next";

export default {
  fetch() {
    return new ImageResponse(<Hello />, {
      width: 1200,
      height: 630,
      format: "webp",
      module,
    });
  },
}

function Hello() {
  return (
    <div tw="bg-white w-full h-full flex items-center justify-center">
      <h1 tw="text-4xl font-bold">Hello</h1>
    </div>
  );
}
```
</Tab>
</Tabs>

### Templates

If you don't have any idea about where to start, or just want quick and easy way to get started, you can use the built-in templates.

```npm
npm i @takumi-rs/template
```

```tsx twoslash
/** @jsxImportSource react */
// ---cut-before---

import DocsTemplateV1 from "@takumi-rs/template/docs-template-v1";
import { ImageResponse } from "@takumi-rs/image-response";
import { Axe } from "lucide-react";

export function GET() {
  return new ImageResponse(
    <DocsTemplateV1 
      title="Hello" 
      description="World" 
      icon={<Axe />} 
      primaryColor="hsla(354, 90%, 54%, 0.3)" 
      primaryTextColor="hsl(354, 90%, 60%)" 
      site="Takumi" 
    />, 
    {
      width: 1200,
      height: 630,
      format: "webp",
    },
  );
}
```

You can find all the templates in the [`takumi-template` folder](https://github.com/kane50613/takumi/tree/master/takumi-template/src/templates).

We need your help to improve and create more templates! Please feel free to submit PRs to add more templates.

## Examples

Check out the [`example` folder](https://github.com/kane50613/takumi/tree/master/example) for different framework usages.

## Learn More

### Why build a satori alternative?

Takumi's focus is on how to rasterize images fast, while satori outputs SVG.

<Callout type="info">
More discussion can be found in [this X thread by @shuding_](https://x.com/shuding_/status/1958853749004542445).
</Callout>

- All in one. No need to output SVG then have [resvg-js](https://github.com/thx/resvg-js) rendering it again to output PNG.
- Inline layout support (display `block` or `inline`).
- Tailwind CSS support out of the box.
- RTL support.
- Variable fonts support.
- COLR font support (e.g. twemoji-colr).
- WOFF2 font format support.
- PNG, JPEG, WebP output support.
- WebP, APNG animation rendering support.
